package com.lanwon.exception;

import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.binding.BindingException;

import java.net.BindException;
import java.net.ConnectException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.dao.DataAccessException;
import org.springframework.http.HttpStatus;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.NoHandlerFoundException;
import javax.servlet.http.HttpServletRequest;
import javax.validation.ConstraintViolationException;

import java.sql.SQLException;
import java.util.List;

/**   
 * <p>Title：GlobalExceptionHandler</P>
 * <p>说明： 统一异常处理类</P>
 * <p>Company: 蓝网科技</p >
 * @project 通用组件 V1.0
 * @author: LiuYZ
 * @date  2019年5月20日
 */
@RestControllerAdvice
public class GlobalExceptionHandler {

    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    /**
     * 处理请求对象属性不满足校验规则的异常信息
     * @param request
     * @param exception
     * @return
     * @throws Exception
     */
    @ExceptionHandler(value = MethodArgumentNotValidException.class)
    public BaseResult exception(HttpServletRequest request, MethodArgumentNotValidException exception) {
        BindingResult result = exception.getBindingResult();
        final List<FieldError> fieldErrors = result.getFieldErrors();
        StringBuilder builder = new StringBuilder();
        for (FieldError error : fieldErrors) {
            builder.append(error.getDefaultMessage());
        }
        return Rsp.fail(builder.toString(), null);
    }

    /**
     * 处理请求单个参数不满足校验规则的异常信息
     * @param request
     * @param exception
     * @return
     * @throws Exception
     */
    @ExceptionHandler(value = ConstraintViolationException.class)
    public BaseResult constraintViolationExceptionHandler(HttpServletRequest request, ConstraintViolationException exception) {
        return Rsp.fail(exception.getMessage(), null);
    }
    
    /**
     * 自定义异常处理（已知异常）
     *
     * @param request
     * @param exception
     * @return
     * @throws Exception
     */
    @ExceptionHandler(value = GlobalException.class)
    public BaseResult globalExceptionHandler(HttpServletRequest request, GlobalException exception) {
        logger.error("已知异常：{}",exception.getMessage());
        if (StringUtils.isNotEmpty(exception.getCode())) {//自定义code
        	return Rsp.res(exception.getCode(),exception.getMessage(), null);
        }
        return Rsp.fail(exception.getMessage(), null);
    }
    
    /**
	 * 404错误异常的捕获
	 * @param e
	 * @return
	 */
	@ExceptionHandler(value={NoHandlerFoundException.class})
	@ResponseStatus(value=HttpStatus.NOT_FOUND)
	public BaseResult badRequestNotFound(BindException e){
		logger.error("找不到该方法：{}",e);
		return Rsp.err("找不到该方法!", null);
	}
 
	/**
	 * mybatis未绑定异常
	 * @param e
	 * @return
	 */
	@ExceptionHandler(BindingException.class)
	@ResponseStatus(value=HttpStatus.INTERNAL_SERVER_ERROR)
	public BaseResult mybatis(Exception e){
		logger.error("mybatis未绑定异常：{}",e);
		return Rsp.err("mybatis未绑定异常，请联系管理员!", null);
	}

	/**
	 * 数据库操作出现异常
	 * @param e
	 * @return
	 */
	@ExceptionHandler(value={SQLException.class,DataAccessException.class})
	@ResponseStatus(value=HttpStatus.INTERNAL_SERVER_ERROR)
	public BaseResult systemError(Exception e){
		logger.error("数据库操作出现异常：{}",e);
		return Rsp.err("数据库异常，请联系管理员!", null);
	}
	
	/**
	 * 网络连接失败！
	 * @param e
	 * @return
	 */
	@ExceptionHandler(value={ConnectException.class})
	@ResponseStatus(value=HttpStatus.INTERNAL_SERVER_ERROR)
	public BaseResult connect(Exception e){
		logger.error("网络连接异常：{}",e);
		return Rsp.err("网络连接异常，请联系管理员!", null);
	}
    
    /**
     * 处理未定义的其他异常信息
     * @param request
     * @param exception
     * @return
     */
    @ExceptionHandler(value = Exception.class)
    public BaseResult exceptionHandler(HttpServletRequest request, Exception exception) {
    	logger.error("未知系统异常：{}",exception);
        return Rsp.err("未知系统异常，请联系管理员!", null);
    }
}
